package com.danceforyou.order.service.impl;

import com.danceforyou.common.model.ConfigDO;
import com.danceforyou.common.restful.exception.BizExceptionEnum;
import com.danceforyou.common.service.ConfigService;
import com.danceforyou.common.service.OperationService;
import com.danceforyou.common.service.impl.BaseServiceImpl;
import com.danceforyou.common.util.*;
import com.danceforyou.customer.model.CustomerDO;
import com.danceforyou.customer.model.CustomerUserDO;
import com.danceforyou.customer.service.CustomerService;
import com.danceforyou.customer.service.CustomerUserService;
import com.danceforyou.medium.model.MediumDO;
import com.danceforyou.medium.service.MediumService;
import com.danceforyou.order.dao.OrderDAO;
import com.danceforyou.order.model.OrderCourseDO;
import com.danceforyou.order.model.OrderDO;
import com.danceforyou.order.service.OrderCourseService;
import com.danceforyou.order.service.OrderService;
import com.danceforyou.order.vo.OrderVO;
import com.danceforyou.payment.model.PaymentDO;
import com.danceforyou.payment.service.PaymentService;
import com.danceforyou.receipt.model.ReceiptDO;
import com.danceforyou.receipt.service.ReceiptService;
import com.danceforyou.salary.model.SalaryEntryDO;
import com.danceforyou.salary.service.SalaryEntryService;
import com.danceforyou.user.vo.UserVO;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import javax.servlet.http.HttpSession;
import java.math.BigDecimal;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
* 类名称：OrderServiceImpl
* 创建人：danceforyou
* 创建时间：2021年02月04日
* 版本号：1.0v
*/
@Service("orderService")
public class OrderServiceImpl extends BaseServiceImpl<Long, OrderDO, OrderVO, OrderDAO> implements OrderService {
    @Autowired
    private OrderDAO orderDAO;
    @Autowired
    private CustomerService customerService;
    @Autowired
    private CustomerUserService customerUserService;
    @Autowired
    private MediumService mediumService;
    @Autowired
    private ConfigService configService;
    @Autowired
    private OrderCourseService orderCourseService;
    @Autowired
    private PaymentService paymentService;
    @Autowired
    private ReceiptService receiptService;
    @Autowired
    private SalaryEntryService salaryEntryService;
    @Autowired
    private OperationService operationService;
    @Autowired(required = false)
    private HttpSession session;

    @Override
    public OrderDAO getDao() {
        return orderDAO;
    }

    /**
     * 计算排期利润
     * @param order 排期信息
     */
    public void calculateProfit(OrderDO order) {
        //获取公司配置（是否精准税额）
        ConfigDO config = configService.getByProperty("configText", Constants.CONFIG_PRECISE_TAX);
        if (config != null && "0".equals(config.getConfigValue())) {//不计算精准税额
            //计算客户税额
            if (order.getCustomerPoint() < 0) {
                //客户税额=执行价*客户税率
                BigDecimal customerPoint = new BigDecimal(-order.getCustomerPoint()).divide(new BigDecimal(100), 2, BigDecimal.ROUND_HALF_UP);
                BigDecimal customerTax = order.getQuotedPrice().multiply(customerPoint).setScale(2, BigDecimal.ROUND_HALF_UP);
                order.setCustomerTax(customerTax);
            } else if (order.getCustomerPoint() == 0) {
                order.setCustomerTax(BigDecimal.ZERO);
            } else {
                //客户税额=执行价*客户税率
                BigDecimal customerPoint = new BigDecimal(order.getCustomerPoint()).divide(new BigDecimal(100), 2, BigDecimal.ROUND_HALF_UP);
                BigDecimal customerTax = order.getQuotedPrice().multiply(customerPoint).setScale(2, BigDecimal.ROUND_HALF_UP);
                order.setCustomerTax(customerTax);
            }
            //计算号主税额
            if (order.getMediumPoint() < 0) {
                //号主税额=成本价*号主税率
                BigDecimal mediumPoint = new BigDecimal(-order.getMediumPoint()).divide(new BigDecimal(100), 2, BigDecimal.ROUND_HALF_UP);
                BigDecimal mediumTax = order.getCostPrice().multiply(mediumPoint).setScale(2, BigDecimal.ROUND_HALF_UP);
                order.setMediumTax(mediumTax);
            } else if (order.getMediumPoint() == 0) {
                order.setMediumTax(BigDecimal.ZERO);
            } else {
                //号主税额=成本价*号主税率
                BigDecimal mediumPoint = new BigDecimal(order.getMediumPoint()).divide(new BigDecimal(100), 2, BigDecimal.ROUND_HALF_UP);
                BigDecimal mediumTax = order.getCostPrice().multiply(mediumPoint).setScale(2, BigDecimal.ROUND_HALF_UP);
                order.setMediumTax(mediumTax);
            }
        } else {//计算精准税额
            //计算客户税额
            if (order.getCustomerPoint() < 0) {
                //客户税额=执行价/(1+客户税率)*客户税率
                BigDecimal customerPoint = new BigDecimal(-order.getCustomerPoint()).divide(new BigDecimal(100), 2, BigDecimal.ROUND_HALF_UP);
                BigDecimal customerTax = order.getQuotedPrice().multiply(customerPoint).divide(BigDecimal.ONE.add(customerPoint), 2, BigDecimal.ROUND_HALF_UP);
                order.setCustomerTax(customerTax);
            } else if (order.getCustomerPoint() == 0) {
                order.setCustomerTax(BigDecimal.ZERO);
            } else {
                //客户税额=执行价/(1+客户税率)*客户税率
                BigDecimal customerPoint = new BigDecimal(order.getCustomerPoint()).divide(new BigDecimal(100), 2, BigDecimal.ROUND_HALF_UP);
                BigDecimal customerTax = order.getQuotedPrice().multiply(customerPoint).divide(BigDecimal.ONE.add(customerPoint), 2, BigDecimal.ROUND_HALF_UP);
                order.setCustomerTax(customerTax);
            }
            //计算号主税额
            if (order.getMediumPoint() < 0) {
                //号主税额=成本价/(1+号主税率)*号主税率
                BigDecimal mediumPoint = new BigDecimal(-order.getMediumPoint()).divide(new BigDecimal(100), 2, BigDecimal.ROUND_HALF_UP);
                BigDecimal mediumTax = order.getCostPrice().multiply(mediumPoint).divide(BigDecimal.ONE.add(mediumPoint), 2, BigDecimal.ROUND_HALF_UP);
                order.setMediumTax(mediumTax);
            } else if (order.getMediumPoint() == 0) {
                order.setMediumTax(BigDecimal.ZERO);
            } else {
                //号主税额=成本价/(1+号主税率)*号主税率
                BigDecimal mediumPoint = new BigDecimal(order.getMediumPoint()).divide(new BigDecimal(100), 2, BigDecimal.ROUND_HALF_UP);
                BigDecimal mediumTax = order.getCostPrice().multiply(mediumPoint).divide(BigDecimal.ONE.add(mediumPoint), 2, BigDecimal.ROUND_HALF_UP);
                order.setMediumTax(mediumTax);
            }
        }
        //获取利润计算公式
        config = configService.getByProperty("configText", Constants.CONFIG_ORDER_PROFIT_FORMULA);
        String profitFormula = "a - b";
        if (config != null && !StringUtil.isBlank(config.getConfigValue())) {
            profitFormula = config.getConfigValue();
        }
        //计算排期利润
        Map<String, BigDecimal> variables = new HashMap<>();
        variables.put("a", order.getQuotedPrice());//执行价
        variables.put("b", order.getCostPrice());//成本价
        variables.put("c", order.getCustomerTax());//客户税额
        variables.put("d", order.getMediumTax());//号主税额
        variables.put("e", order.getCustomerRebates());//客户返点
        variables.put("f", order.getMediumRebates());//号主返点
        variables.put("g", BigDecimal.valueOf(order.getCustomerPoint()));//客户税点
        variables.put("h", BigDecimal.valueOf(order.getMediumPoint()));//号主税点
        BigDecimal profit = CalculateUtil.calculate(profitFormula, variables);
        AssertUtil.notNull(profit, "计算利润失败，请联系技术人员");
        order.setProfit(profit);
        if (BigDecimal.ZERO.compareTo(order.getQuotedPrice()) == 0) {
            order.setProfitRate(BigDecimal.ZERO);
        } else {
            order.setProfitRate(order.getProfit().multiply(new BigDecimal(100)).divide(order.getQuotedPrice(), 2, BigDecimal.ROUND_HALF_UP));
        }
    }

    @Override
    public void saveInfo(OrderDO order) {
        UserVO loginUser = (UserVO) session.getAttribute(Constants.SESSION_USER);
        AssertUtil.notNull(loginUser, BizExceptionEnum.AUTHFAILURE);
        //获取客户信息
        CustomerDO customer = customerService.getById(order.getCustomerId());
        AssertUtil.notNull(customer, "客户信息不存在，非法操作");
        AssertUtil.isTrue(customer.getStatus() == Constants.CUSTOMER_STATUS_ENABLE, "该客户未启用，非法操作");
        //获取客户授权信息
        CustomerUserDO customerUser = customerUserService.getByCondition(new HashMap<String, Object>(){{
            put("customerId", customer.getId());
            put("belongUserId", loginUser.getId());
        }});
        AssertUtil.notNull(customerUser, "您暂无该客户权限或授权已过期");
        //获取公众号信息
        MediumDO medium = mediumService.getById(order.getMediumId());
        AssertUtil.notNull(medium, "公众号信息不存在");
        AssertUtil.isTrue(medium.getStatus() == Constants.MEDIUM_STATUS_ENABLE, "公众号已停用或已删除");
        //计算利润
        calculateProfit(order);
        //补充排期信息
        order.setCreateUserId(loginUser.getId());
        order.setCreateDate(new Date());
        order.setIsReceipt(order.getQuotedPrice().compareTo(BigDecimal.ZERO) <= 0);
        order.setIsPayment(order.getCostPrice().compareTo(BigDecimal.ZERO) <= 0);
        order.setIsSettle(false);
        order.setIsDelete(false);
        this.insert(order);
        //记录排期历程
        OrderCourseDO orderCourse = new OrderCourseDO();
        BeanUtils.copyProperties(order, orderCourse);
        orderCourse.setId(null);
        orderCourse.setOrderId(order.getId());
        orderCourse.setOperUserId(loginUser.getId());
        orderCourse.setOperDate(new Date());
        orderCourse.setIsDelete(false);
        orderCourseService.insert(orderCourse);
        //记录操作日志
        operationService.saveOperation(Constants.OPER_TABLE_ORDER, order.getId(), Constants.OPER_ADD, loginUser, null);
    }

    @Override
    public void updateInfo(OrderDO order) {
        UserVO loginUser = (UserVO) session.getAttribute(Constants.SESSION_USER);
        AssertUtil.notNull(loginUser, BizExceptionEnum.AUTHFAILURE);
        OrderDO temp = this.getById(order.getId());
        AssertUtil.notNull(temp, "信息不存在");
        AssertUtil.isTrue(!temp.getIsSettle(), "该排期已结算，无法修改");
        //计算利润
        calculateProfit(order);
        order.setIsReceipt(order.getQuotedPrice().compareTo(BigDecimal.ZERO) <= 0);
        order.setIsPayment(order.getCostPrice().compareTo(BigDecimal.ZERO) <= 0);
        this.update(order);
        //记录排期历程
        OrderCourseDO orderCourse = new OrderCourseDO();
        BeanUtils.copyProperties(order, orderCourse);
        orderCourse.setId(null);
        orderCourse.setOrderId(order.getId());
        orderCourse.setOperUserId(loginUser.getId());
        orderCourse.setOperDate(new Date());
        orderCourse.setIsDelete(false);
        orderCourseService.insert(orderCourse);
        //记录操作日志
        operationService.saveOperation(Constants.OPER_TABLE_ORDER, order.getId(), Constants.OPER_EDIT, loginUser, null);
    }

    @Override
    public int deleteInfoByIds(String ids) {
        UserVO loginUser = (UserVO) session.getAttribute(Constants.SESSION_USER);
        AssertUtil.notNull(loginUser, BizExceptionEnum.AUTHFAILURE);
        String[] idArr = ids.split(",");
        int i = 0;
        for (String id : idArr) {
            OrderDO order = this.getById(Long.valueOf(id));
            AssertUtil.notNull(order, "信息不存在");
            AssertUtil.isTrue(!order.getIsSettle(), "该排期已结算，无法删除");
            this.setDelete(order);
            //删除付款申请
            List<PaymentDO> paymentList = paymentService.listByCondition(new HashMap<String, Object>(){{
                put("orderId", order.getId());
                put("isDelete", false);
            }});
            for (PaymentDO payment : paymentList) {
                paymentService.setDelete(payment);
                //记录操作日志
                operationService.saveOperation(Constants.OPER_TABLE_PAYMENT, payment.getId(), Constants.OPER_DELETE, loginUser, "删除排期时删除");
            }
            //删除回款申请
            List<ReceiptDO> receiptList = receiptService.listByCondition(new HashMap<String, Object>(){{
                put("orderId", order.getId());
                put("isDelete", false);
            }});
            for (ReceiptDO receipt : receiptList) {
                receiptService.setDelete(receipt);
                //记录操作日志
                operationService.saveOperation(Constants.OPER_TABLE_RECEIPT, receipt.getId(), Constants.OPER_DELETE, loginUser, "删除排期时删除");
            }
            //记录排期历程
            OrderCourseDO orderCourse = new OrderCourseDO();
            BeanUtils.copyProperties(order, orderCourse);
            orderCourse.setId(null);
            orderCourse.setOrderId(order.getId());
            orderCourse.setOperUserId(loginUser.getId());
            orderCourse.setOperDate(new Date());
            orderCourse.setIsDelete(true);
            orderCourseService.insert(orderCourse);
            //记录操作日志
            operationService.saveOperation(Constants.OPER_TABLE_ORDER, order.getId(), Constants.OPER_DELETE, loginUser, null);
        }
        return i;
    }

    @Override
    public int setOrderSettle(String ids) {
        UserVO loginUser = (UserVO) session.getAttribute(Constants.SESSION_USER);
        AssertUtil.notNull(loginUser, BizExceptionEnum.AUTHFAILURE);
        String[] idArr = ids.split(",");
        int i = 0;
        SimpleDateFormat format = new SimpleDateFormat("yyyyMM");
        Date settleDate = new Date();
        for (String id : idArr) {
            OrderDO order = this.getById(Long.valueOf(id));
            AssertUtil.notNull(order, "信息不存在");
            AssertUtil.isTrue(!order.getIsDelete(), "信息不存在");
            AssertUtil.isTrue(order.getIsPayment(), "该排期未支付，无法结算");
            AssertUtil.isTrue(order.getIsReceipt(), "该排期未回款，无法结算");
            AssertUtil.isTrue(!order.getIsSettle(), "该排期已结算，请勿重复操作");
            order.setIsSettle(true);
            i += this.update(order);
            MediumDO medium = mediumService.getById(order.getMediumId());
            AssertUtil.notNull(medium, "公众号信息不存在");
            //生成媒介业绩条目
            SalaryEntryDO entry = new SalaryEntryDO();
            entry.setOrderId(order.getId());
            entry.setType(1);
            entry.setMoney(order.getProfit());
            entry.setBelongUserId(medium.getCreateUserId());
            entry.setBelongMonth(format.format(settleDate));
            entry.setCreateDate(settleDate);
            salaryEntryService.insert(entry);
            //生成销售业绩条目
            entry.setType(2);
            entry.setBelongUserId(order.getCreateUserId());
            salaryEntryService.insert(entry);
            //记录操作日志
            operationService.saveOperation(Constants.OPER_TABLE_ORDER, order.getId(), Constants.OPER_SETTLE, loginUser, null);
        }
        return i;
    }

    @Override
    public Map<String, Object> statOrderInfo(String roleType, Long userId, String putDate) {
        return orderDAO.statOrderInfo(roleType, userId, putDate);
    }

    @Override
    public List getRankList() {
        return orderDAO.getRankList();
    }
}
